<?php
/**
 * Created by stoneshi
 * Email: 2213152917@qq.com
 * Date: 2017/7/7
 * Time: 18:17
 */
namespace Tiger\Components;

use GuzzleHttp\Client;
use GuzzleHttp\Cookie\CookieJar;
use GuzzleHttp\Cookie\SetCookie;
use GuzzleHttp\Promise;
use GuzzleHttp\Psr7\Response;

class HttpClient
{
    protected $_currentUrl        = '';

    protected $_options           = array();

    protected $_cookies           = array();

    protected $_domain            = array();

    protected $_proxy             = array();

    protected static $_client     = null;

    protected $promises           = array();


    /**
     * Http default options
     * @var array
     */
    public static $_defaultOptions = array(
        'timeout'         => 60,
        'connect_timeout' => 60,
        'verify'          => false,
        'headers'         => array(
            'User-Agent' => 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
        ),
        'curl'            => array(
            CURLOPT_FRESH_CONNECT => 1,
            CURLOPT_FORBID_REUSE  => 1
        )
    );

    public function __construct($url = '')
    {
        $this->addRequestUrl($url);
    }

    public function get($url = '')
    {
        $client = self::_getClient();
        if (isset($this->_cookies[$this->_currentUrl]))
        {
            $this->_options[$this->_currentUrl]['cookies'] = $this->_getCookiesJar($this->_cookies[$this->_currentUrl], $this->_domain[$this->_currentUrl]);
        }
        if (isset($this->_proxy[$this->_currentUrl]))
        {
            $this->_options[$this->_currentUrl]['proxy'] = $this->_proxy[$this->_currentUrl];
        }
        $furl = empty($url) ? $this->_currentUrl : $url;
        $this->promises[$this->_currentUrl] = $client->getAsync($furl, $this->_options[$this->_currentUrl]);
    }

    public function post($data, $url = '')
    {
        $client = self::_getClient();
        if (isset($this->_cookies[$this->_currentUrl]))
        {
            $this->_options[$this->_currentUrl]['cookies'] = $this->_getCookiesJar($this->_cookies[$this->_currentUrl], $this->_domain[$this->_currentUrl]);
        }
        if (isset($this->_proxy[$this->_currentUrl]))
        {
            $this->_options[$this->_currentUrl]['proxy'] = $this->_proxy[$this->_currentUrl];
        }
        $this->_options[$this->_currentUrl]['body'] = $data;
        $furl = empty($url) ? $this->_currentUrl : $url;
        $this->promises[$this->_currentUrl] = $client->getAsync($furl, $this->_options[$this->_currentUrl]);
    }

    public function getResponse($url = '')
    {
        $results = array();
        $response = Promise\unwrap($this->promises);
        if (!empty($url) && isset($response[$url]))
        {
            $results = $this->_parseResponse($response[$url]);
        }
        else
        {
            foreach ($response as $url => $resp)
            {
                $results[$url] = $this->_parseResponse($resp);
            }
        }
        $this->promises = array();
        return $results;


    }
    protected static function _getClient($options = array())
    {
        if (empty(self::$_client))
        {
            self::$_client = new Client($options);
        }
        return self::$_client;
    }

    public function addRequestUrl($url = '')
    {
        if (!empty($url))
        {
            $this->_currentUrl = $url;
            $this->_options[$url] = self::$_defaultOptions;
            $parse = parse_url($url);
            if (isset($parse['host']))
                $this->_domain[$url] = $parse['host'];

        }
        return $this;
    }

    public function setProxy($domain, $port)
    {
        $this->_proxy[$this->_currentUrl] = "tcp://{$domain}:{$port}";
        return $this;
    }

    public function setConnectTimeout($time = 60)
    {
        $this->_options[$this->_currentUrl]['connect_timeout'] = $time;
        return $this;
    }

    public function setTimeout($time = 60)
    {
        $this->_options[$this->_currentUrl]['timeout'] = $time;
        return $this;
    }

    public function setHeaders($headers = array())
    {
        if (!empty($headers))
        {
            $this->_options[$this->_currentUrl]['headers'] = array_merge($this->_options[$this->_currentUrl]['headers'], $headers);
        }
        return $this;
    }

    public function setCookies($cookies = '')
    {
        if (!empty($cookies))
        {
            $this->_cookies[$this->_currentUrl] = $cookies;
        }
    }

    protected function _parseResponse(Response $response)
    {
        return array(
            'body'    => (string)$response->getBody(),
            'code'    => $response->getStatusCode(),
            'headers' => $response->getHeaders()
        );
    }

    protected function _getCookiesJar($cookies = '', $domain = '')
    {
        $cookies    = SetCookie::fromString($cookies);
        $cookiesJar = CookieJar::fromArray($cookies->toArray(), $domain);
        return $cookiesJar;
    }
}